package org.example.chat.security.components.filter;

import org.example.chat.security.components.utils.JWTUtils;
import org.example.chat.security.config.SecurityConfigProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 解析token中的用户信息,并将认证信息设置到spring security 全局上下文中
 * SecurityContextHolder.getContext().setAuthentication()
 * @author cheval
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private SecurityConfigProperties properties;
    @Autowired
    private JWTUtils jwtUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 1. 判断请求是否是白名单之一，如果是直接放行
        String requestURI = request.getRequestURI();
        String contextPath = request.getContextPath();
        for (String url : properties.getIgnoreUrls()) {
            if (requestURI.equals(contextPath + url)) {
                filterChain.doFilter(request,response);
                return;
            }
        }
        // 2. 根据token设置登录状态
        String headerName = "Authorization";
        String bearer = "Bearer";
        String tokenHeader = request.getHeader(headerName);
        if (tokenHeader != null && tokenHeader.startsWith(bearer)) {
            String token = tokenHeader.substring(bearer.length() + 1);
            // 判断token是否有效
            if (jwtUtils.isValid(token)) {
                // 判断是否有登录状态
                if (SecurityContextHolder.getContext().getAuthentication() == null) {
                    // 设置登录状态
                    UserDetails userDetails = jwtUtils.getUserInfoFromToken(token);
                    Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails,null,null);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        }
        filterChain.doFilter(request,response);
    }
}
